package com.orhon.smartcampus.basicComponents.router;

import java.io.IOException;
import java.net.URL;
import java.util.Date;

import com.orhon.smartcampus.modules.notice.fetcher.NoticeFetchersLoader;
import com.orhon.smartcampus.modules.course.fetcher.CourseFetchersLoader;
import com.orhon.smartcampus.modules.schoolaffairs.fetcher.SchoolNewNoticeFetchersLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 *
 * 整合第三方工具，整合springboot
 * 2019年
 * @Author M
 *
 */

import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import com.orhon.smartcampus.modules.base.fetcher.BaseFetchersLoader;
import com.orhon.smartcampus.modules.baseinfo.fetcher.BaseInfoFetcherLoader;
import com.orhon.smartcampus.modules.core.gql.scalars.ExtendedScalars;
import com.orhon.smartcampus.modules.material.fetcher.MaterialFetchersLoader;
import com.orhon.smartcampus.modules.student.fetcher.StudentFetchersLoader;
import com.orhon.smartcampus.modules.systemctl.fetcher.SystemCtlFetchersLoader;
import com.orhon.smartcampus.modules.teacher.fetcher.TeacherFetchersLoader;
import com.orhon.smartcampus.modules.user.fetcher.UserFetchersLoader;

import graphql.schema.Coercing;
import graphql.schema.CoercingParseLiteralException;
import graphql.schema.CoercingParseValueException;
import graphql.schema.CoercingSerializeException;
import graphql.schema.GraphQLScalarType;
import graphql.schema.GraphQLSchema;
import graphql.schema.StaticDataFetcher;
import graphql.schema.idl.RuntimeWiring;
import graphql.schema.idl.SchemaGenerator;
import graphql.schema.idl.SchemaParser;
import graphql.schema.idl.TypeDefinitionRegistry;

@Component
public class SpringBootStart {

	protected final static String TYPE_QUERY = "Query";
	protected final static String TYPE_MUTATION = "Mutation";

	public final static String SCHEMA_ROOT = "graphql/root.graphqls";
	public final static String SCHEMA_BASIC = "graphql/basic.graphqls";
	public final static String SCHEMA_USER = "graphql/user.graphqls";
	public final static String SCHEMA_TEACHER = "graphql/teacher.graphqls";
	public final static String SCHEMA_STUDENT = "graphql/student.graphqls";
	public final static String SCHEMA_ECLASS = "graphql/eclass.graphqls";
	public final static String SCHEMA_MATERIAL = "graphql/material.graphqls";
	public final static String SCHEMA_SCHOOLBASEINFO= "graphql/schoolbaseinfo.graphqls";
	public final static String SCHEMA_SYSTEMCTL= "graphql/systemctl.graphqls";
	public final static String SCHEMA_MESSAGE= "graphql/message.graphqls";
    public final static String SCHEMA_NOTICE= "graphql/notice.graphqls";
    public final static String SCHEMA_STATISTICS= "graphql/teacherstatistics.graphqls";


	@Autowired
	SystemCtlFetchersLoader systemCtlFetchersLoader;

	@Autowired
	UserFetchersLoader userFetchersLoaderl;

	@Autowired
	StudentFetchersLoader studentFetchersLoader;

	@Autowired
	TeacherFetchersLoader teacherFetchersLoader;

	@Autowired
	BaseInfoFetcherLoader baseInfoFetcherLoader;

	@Autowired
	BaseFetchersLoader baseFetchersLoader;

	@Autowired
	MaterialFetchersLoader materialFetchersLoader;

	@Autowired
	CourseFetchersLoader courseFetchersLoader;

	@Autowired
	NoticeFetchersLoader noticeFetchersLoader;

	@Autowired
	SchoolNewNoticeFetchersLoader schoolNewNoticeFetchersLoader;

	@Bean
	public GraphQLSchema schema() throws IOException {
		GraphQLSchema schema = loadSchma();
		return schema;
	}

	public void init(){

	}


	/**
	 * 定义schema文件列表...
	 */
	protected  String[] getSchemas(){
		return new String[]{SCHEMA_ROOT , SCHEMA_BASIC ,SCHEMA_USER , SCHEMA_TEACHER ,SCHEMA_STUDENT, SCHEMA_ECLASS,SCHEMA_MATERIAL, SCHEMA_SCHOOLBASEINFO,SCHEMA_SYSTEMCTL,SCHEMA_STATISTICS,SCHEMA_NOTICE,SCHEMA_MESSAGE };
	}

	/**
	 * 获取graphql schema结构...
	 */
	private GraphQLSchema loadSchma() throws IOException {
		SchemaParser parser = new SchemaParser();
		SchemaGenerator generator = new SchemaGenerator();
		String[] fileList = getSchemas();
		TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry();
		for(String current: fileList) {
			String schemaSDL = loadSchemaFile(current);
			typeRegistry.merge(parser.parse(schemaSDL));
		}
		GraphQLSchema schema = generator.makeExecutableSchema(typeRegistry, buildDynamicRuntimeWiring());
		return schema;
	}

	/**
	 * 加载schema文件
	 * @param fileName
	 * @return
	 * @throws IOException
	 */
	protected String loadSchemaFile(String fileName) throws IOException {
		URL url = Resources.getResource(fileName);
		String sdl = Resources.toString(url, Charsets.UTF_8);
		return sdl;
	}


	/**
	 * 自定义变量 ， 本办法在框架中被抛弃，需要重构　。。。
	 */
	public static final GraphQLScalarType GQLDate = new GraphQLScalarType("Date" , "" , new Coercing(){

		@Override
		public Object serialize(Object dataFetcherResult) throws CoercingSerializeException {
			Date d = (Date)dataFetcherResult;
			Long orgData = d.getTime();
			return orgData / 1000;
		}

		@Override
		public Object parseValue(Object input) throws CoercingParseValueException {
			return input;
		}

		@Override
		public Object parseLiteral(Object input) throws CoercingParseLiteralException {
			return input;
		}
	});


	protected RuntimeWiring buildDynamicRuntimeWiring() {
		RuntimeWiring.Builder builder = RuntimeWiring.newRuntimeWiring();

		//builder.scalar(GQLDate);
		builder.scalar(ExtendedScalars.Time);
		builder.scalar(ExtendedScalars.DateTime);
		builder.scalar(ExtendedScalars.Date);
		builder.scalar(ExtendedScalars.Json);
		builder.scalar(ExtendedScalars.Object);
		builder.scalar(ExtendedScalars.Locale);

		builder.type(TYPE_QUERY , typeWiring-> typeWiring.dataFetcher("hello" , new StaticDataFetcher("world")));

		//系统设置加载..
		systemCtlFetchersLoader.LoadFetchers(builder);
		//用户fetchers加载
		userFetchersLoaderl.LoadFetchers(builder);
		//学生fetchers加载
		studentFetchersLoader.LoadFetchers(builder);
		//教师fetchers加载
		teacherFetchersLoader.LoadFetchers(builder);
		//baseinfo fetchers load
		baseInfoFetcherLoader.LoadFetchers(builder);
		//base  fetchers 加载
		baseFetchersLoader.LoadFetchers(builder);
		//material fetcher 加载
		materialFetchersLoader.LoadFetchers(builder);
		//material fetcher 加载
		materialFetchersLoader.LoadFetchers(builder);
		//课程fetcher加载
		courseFetchersLoader.LoadFetchers(builder);
		//通知公告fetcher加载
		noticeFetchersLoader.LoadFetchers(builder);
		//校务综合 新闻/公告/通知加载
		schoolNewNoticeFetchersLoader.LoadFetchers(builder);

		return builder.build();
	}
}
